package hn.sigit.util;

import java.math.BigDecimal;
import java.math.RoundingMode;

public class GeneralUtils {
	private static final String[] ES_UNITS = {"", "un", "dos", "tres", "cuatro", "cinco",
		"seis", "siete", "ocho", "nueve", "diez", "once", "doce", "trece", "catorce", "quince",
		"dieciseis", "diecisiete", "dieciocho", "diecinueve", "veinte", "veintiun", "veintidos",
		"veintres", "veinticuatro", "veinticinco", "veintiseis", "veintisiete", "veintiocho",
		"veintinueve"};
	private static final String[] ES_TENS = {"", "diez", "veinte", "treinta", "cuarenta",
		"cincuenta", "sesenta", "setenta", "ochenta", "noventa"};
	private static final String[] ES_HUNDREDS = {"", "ciento", "doscientos", "trescientos",
		"cuatrocientos", "quinientos", "seiscientos", "setecientos", "ochocientos", "novecientos"};
	
	
	private static String spanishConvertNumberToWordsAux(int number) {
		if (number < 30)
			return ES_UNITS[number];
		else if (number < 100) {
			return ES_TENS[number / 10] + (number % 10 > 0 ? " y " + ES_UNITS[number % 10] : "");
		}
		else if (number < 1000) {
			if (number == 100)
				return "cien";
			return ES_HUNDREDS[number / 100] + (number % 100 > 0 ? " " + spanishConvertNumberToWordsAux(number % 100) : "");
		}
		
		return "";
	}
	
	public static String spanishConvertNumberToWords(long number) {
		if (number == 0)
			return "cero";
		
		StringBuilder sb = new StringBuilder();
		
		if (number < 0) {
			sb.append("menos ");
			number *= -1;
		}
		
		long n = number;
		long remainingDigits = 1L;
		long divisor = 1L;
		
		while (divisor * 10 <= n) {
			divisor *= 10;
			remainingDigits += 1;
		}
		int digitsToTake = (int) ((remainingDigits-1) % 3 + 1);
		
		for (int i = 0; i < digitsToTake - 1; i++)
			divisor /= 10;
		
		String txt;
		do {
			txt = spanishConvertNumberToWordsAux((int) (n / divisor));
			if (!txt.trim().equals(""))
				sb.append(txt + " ");

			remainingDigits -= digitsToTake;
			if (remainingDigits > 0) {
				if (remainingDigits % 6 == 0) {
					if (number / divisor > 1)
						sb.append("millones ");
					else
						sb.append("millon ");
				}
				else if (remainingDigits % 3 == 0) {
					if (n / divisor > 0)
						sb.append("mil ");
				}
			}
			else
				break;
			
			n -= n/divisor * divisor;
			
			digitsToTake = (int) ((remainingDigits-1) % 3 + 1);
			for (int i = 0; i < digitsToTake; i++)
				divisor /= 10;
		} while (true);
		
		sb.deleteCharAt(sb.length()-1);
		return sb.toString();
	}
	
	public static String spanishConvertNumberToWords(BigDecimal bd) {
		return spanishConvertNumberToWords(bd, null, null, null);
	}
	
	public static String spanishConvertNumberToWords(BigDecimal bd, String intSuffix, String fractPrefix, String fractSuffix) {
		if (bd == null)
			return "(valor no especificado)";
		
		StringBuilder sb = new StringBuilder();
		
		bd = bd.setScale(2, RoundingMode.HALF_UP);
		
		long intPart = bd.longValue();
		long fractionalPart = bd.remainder(BigDecimal.ONE).scaleByPowerOfTen(bd.scale()).longValue();
		
		
		sb.append(spanishConvertNumberToWords(intPart));
		if (intSuffix != null && !intSuffix.trim().equals(""))
			sb.append(String.format(" %s", intSuffix));
		
		if (fractionalPart > 0) {
			if (fractPrefix != null && !fractPrefix.trim().equals(""))
				sb.append(String.format(" %s ", fractPrefix));
			else
				sb.append(" punto ");
			sb.append(spanishConvertNumberToWords(fractionalPart));
			if (fractSuffix != null && !fractSuffix.trim().equals(""))
				sb.append(String.format(" %s ", fractSuffix));
		}
		
		return sb.toString().trim();
	}
}
